package com.newly.common.core.service.core.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.newly.common.base.entity.sys.api.ApiDto;
import com.newly.common.core.utils.ClassUtils;
import com.newly.profile.property.PackageProperty;
import com.newly.profile.property.ServerProperty;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @program: newly-parent
 * @remark:
 * @author: guan
 * @create: 2022-01-09 18:28
 */
public class AbstractCoreService {

    @Autowired
    protected PackageProperty packageProperty;

    @Autowired
    protected ServerProperty serverProperty;

    protected Set<String> scanApiPackege() {
        List<String> apis = packageProperty.getApis();
        if (ObjectUtil.isEmpty(apis)) return null;

        // 得到当前包与所有子包下的全类名
        Set<String> classNames = new HashSet<>(128);
        for (String api : apis) {
            List<String> className = ClassUtils.getClassName(api, true);
            if (ObjectUtil.isEmpty(className)) continue;
            classNames.addAll(className);
        }
        return classNames;
    }

    /**
     * 得到ApiDto对象
     *
     * @param classPath 类路劲
     * @return list ApiDto.class
     */
    protected List<ApiDto> packageApiDtos(String classPath) throws Exception {
        if (StrUtil.isBlank(classPath)) return null;

        List<ApiDto> apiDtos = new ArrayList<>(32);
        Class<?> clazz = Class.forName(classPath);
        // 得到FeignClient注解
        FeignClient feignClient = clazz.getDeclaredAnnotation(FeignClient.class);
        if (ObjectUtil.isEmpty(feignClient)) return null;

        // 得到所有方法
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            Annotation[] methodAnnos = method.getDeclaredAnnotations();

            ApiDto apiDto = new ApiDto();
            String prefixUrl = feignClient.path();
            String url = null;
            String remark = null;
            String apiMethod = null;
            for (Annotation methodAnno : methodAnnos) {
                String[] suffixUrls = null;
                if (methodAnno instanceof GetMapping) {
                    GetMapping getMapping = (GetMapping) methodAnno;
                    suffixUrls = getMapping.value();
                    apiMethod = "GET";
                } else if (methodAnno instanceof PostMapping) {
                    PostMapping postMapping = (PostMapping) methodAnno;
                    suffixUrls = postMapping.value();
                    apiMethod = "POST";
                } else if (methodAnno instanceof DeleteMapping) {
                    DeleteMapping deleteMapping = (DeleteMapping) methodAnno;
                    suffixUrls = deleteMapping.value();
                    apiMethod = "DELETE";
                } else if (methodAnno instanceof PutMapping) {
                    PutMapping putMapping = (PutMapping) methodAnno;
                    suffixUrls = putMapping.value();
                    apiMethod = "PUT";
                } else if (methodAnno instanceof ApiOperation) {
                    ApiOperation putMapping = (ApiOperation) methodAnno;
                    remark = putMapping.value();
                }

                if (ObjectUtil.isEmpty(suffixUrls) && StrUtil.isBlank(remark)) {
                    return null;
                }

                // 得到完成的url
                if (!ObjectUtil.isEmpty(suffixUrls)) {
                    StringBuilder sb = new StringBuilder();
                    for (String suffixUrl : suffixUrls) {
                        if (!prefixUrl.endsWith("/") && !suffixUrl.startsWith("/")) {
                            suffixUrl = "/" + suffixUrl;
                        } else if (prefixUrl.startsWith("/") && suffixUrl.endsWith("/")) {
                            suffixUrl = suffixUrl.substring(1, suffixUrl.length());
                        }
                        sb.append(prefixUrl);
                        sb.append(suffixUrl);
                        sb.append(",");
                    }
                    url = sb.substring(0, sb.length() - 1);
                }
            }

            if (!StrUtil.isBlank(url)) {
                apiDto.setUrl(url);
                apiDto.setRemark(remark);
                apiDto.setMethod(apiMethod);
                apiDtos.add(apiDto);
            }
        }

        return apiDtos;
    }
}
